using System.Collections.Generic;
using Config;
using Entity.Monster;
using Entity.Player.State;
using Map.MapObject;
using MoonFramework.Buff;
using MoonFramework.Scripts.Event;
using MoonFramework.Scripts.Mono;
using MoonFramework.Scripts.Tool.System.Setting;
using Tool.Name;
using UnityEngine;

namespace Entity.Player
{
    public class Player : Character
    {
        private readonly Dictionary<Collider, BaseMapObject> _mapObjectCache = new();
        private readonly Dictionary<Collider, MonsterObject> _monsterCache = new();
        
        public override void Init(EntityData entityData, ActorViewController viewController)
        {
            base.Init(entityData, viewController);
            ActorConfig = ConfigManager.Instance.GetConfig<PlayerConfig>(ConfigName.Player, 0);
            //初始化动画。默认动画配置
            viewController._AttackAnimation = AnimationConfig.PickUp;
            viewController._IdleAnimation = AnimationConfig.Idle;
            viewController._RunAnimation = AnimationConfig.Run;
            viewController._DeadAnimation = AnimationConfig.Dead;
            viewController._WalkAnimation = AnimationConfig.Walk;
            PlayerController.Instance.Init(this);
            viewController.transform.localPosition = entityData.position;
            viewController.transform.localRotation = Quaternion.Euler(entityData.rotation);
            
            //初始化面板属性
            EventCenter.Instance.Callback(EventName.UpdateHp, playerData.Hp);
            EventCenter.Instance.Callback(EventName.UpdateHunger, playerData.Hunger);
            
            WalkSpeed = PlayerConfig.WalkSpeed;
            RunSpeed = PlayerConfig.RunSpeed;
            RotationSpeed = PlayerConfig.RotationSpeed;

            fsmMachine = new PlayerFsm();
            fsmMachine.Init(nameof(PlayerIdleState), this);
            buffFsm = new BuffFsm();
            buffFsm.Init(this);
            
            MonoManager.Instance.SendUpdateEvent(OnUpdate);
        }

        private void OnUpdate()
        {
            OnStateDown();
            Move();
        }

        #region 任务驱动
        protected override void RegisterEvent()
        {
            base.RegisterEvent();
            EventCenter.Instance.Register<RaycastHit>(EventName.RayCast);
            EventCenter.Instance.Register<Collider, bool>(EventName.RemoveMapObject);
            EventCenter.Instance.Register(EventName.SaveGame);
        }

        protected override void SendEvent()
        {
            base.SendEvent();
            EventCenter.Instance.SendCommand<RaycastHit>(EventName.RayCast, OnSelectMapObject);
            EventCenter.Instance.SendCommand<Collider, bool>(EventName.RemoveMapObject, OnRemoveMapObject);
            EventCenter.Instance.SendCommand(EventName.SaveGame, OnGameClose);
        }

        protected override void RemoveEvent()
        {
            base.RemoveEvent();
            EventCenter.Instance.RemoveCommand<RaycastHit>(EventName.RayCast, OnSelectMapObject);
            EventCenter.Instance.RemoveCommand<Collider, bool>(EventName.RemoveMapObject, OnRemoveMapObject);
            EventCenter.Instance.RemoveCommand(EventName.SaveGame, OnGameClose);
        }
        #endregion

        #region 状态驱动
        [HideInInspector] public float hor,ver;
        private readonly Dictionary<Collider, bool> _idDic = new(); // false代表MapObject类型, true代表MonsterObject
        
        private void OnRemoveMapObject(Collider collider, bool type)
        {
            _idDic.Add(collider, type);
        }

        /// <summary>
        /// 选中地图对象 / AI对象 
        /// </summary>
        private void OnSelectMapObject(RaycastHit hitInfo)
        {
            var hitInfoCollider = hitInfo.collider;
            if (_idDic.TryGetValue(hitInfoCollider, out var type))
            {
                if (type) _mapObjectCache.Remove(hitInfoCollider);
                else _monsterCache.Remove(hitInfoCollider);
            }
            // 尝试从缓存中获取
            if (!_mapObjectCache.TryGetValue(hitInfoCollider, out BaseMapObject mapObject))
                mapObject = hitInfoCollider.TryGetComponent(out mapObject) ? mapObject : null;
            if (!_monsterCache.TryGetValue(hitInfoCollider, out MonsterObject monsterObject))
                monsterObject = hitInfoCollider.TryGetComponent(out monsterObject) ? monsterObject : null;

            if (!mapObject && !monsterObject) return;
            
            float dir = Vector3.Distance(viewController.transform.position,
                mapObject ? mapObject.transform.position : monsterObject.transform.position);
            
            if (mapObject)
            {
                _mapObjectCache.TryAdd(hitInfoCollider, mapObject);
                if (mapObject.DoHit(this, dir))
                    fsmMachine?.ChangeState(nameof(PlayerAttackState));
            }
            else if (monsterObject)
            {
                _monsterCache.TryAdd(hitInfoCollider, monsterObject); 
                dir -= ((ItemWeaponInfo)WeaponController.CurrentWeapon.WeaponData.Config.ItemTypeInfo)
                            .AttackDistance; 
                //交互距离：武器长度 + AI半径 (dir - AttackDistance <= AI半径)
                if (monsterObject.DoHit(this, dir))
                    fsmMachine?.ChangeState(nameof(PlayerAttackState));
            }
        }

        private void Move()
        {
            hor = Input.GetAxis("Horizontal");
            ver = Input.GetAxis("Vertical");
            if (fsmMachine.curState == nameof(PlayerDeadState)) return;
            if (Mathf.Abs(hor) + Mathf.Abs(ver) == 0)
                fsmMachine?.ChangeState(nameof(PlayerIdleState));
            else
                fsmMachine?.ChangeState(Input.GetKey(KeyCode.LeftShift) ? nameof(PlayerRunState): nameof(PlayerWalkState));
        }
        #endregion
        
        private void OnGameClose()
        {
            //把存档数据实际存入磁盘
            MonoManager.Instance.RemoveUpdateEvent(OnUpdate);
            ((PlayerViewController)viewController).OnGameOver();
            viewController.OnGameClose();
            RemoveEvent();
        }
    }
}
